﻿
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace DZParallelLib.DZImage
{
    /// <summary>
    /// This completely describes an image at a particular level, in particular what tiles make it up,
    /// the size of each of the tiles, and where the tiles start in the image's overall bitmap coordinates.
    /// </summary>
    /// <remarks>
    /// The info here was where I understood how overlap works: http://www.gasi.ch/blog/inside-deep-zoom-2/
    /// </remarks>
    internal class DZImageLevelDescriptor
    {
        private ulong _tileSize;
        private ulong _overlap;

        /// <summary>
        /// Pre-calculated setup for the tiles at a particular size.
        /// </summary>
        /// <param name="size"></param>
        /// <param name="TileSize"></param>
        /// <param name="Overlap"></param>
        public DZImageLevelDescriptor(Size size, ulong TileSize, ulong Overlap)
        {
            Size = size;
            _tileSize = TileSize;
            _overlap = Overlap;
        }

        /// <summary>
        /// Returns the size of the image in pixels.
        /// </summary>
        public Size Size { get; private set; }

        /// <summary>
        /// Info on one of the tiles in an image.
        /// </summary>
        public class DZImageTileDescriptor
        {
            public ulong X { get; set; }
            public ulong Y { get; set; }
            public uint Width { get; set; }
            public uint Height { get; set; }

            public string Name { get; set; }
        }

        public IEnumerable<DZImageTileDescriptor> Images { get { return ImageList(); } }

        /// <summary>
        /// Enumerator that returns the each tile descriptor one at a time. We generate this on the fly
        /// because for some of the bigger images there can be 1000's of these things, so this allows us
        /// to keep memory under control to some extent.
        /// </summary>
        /// <returns></returns>
        private IEnumerable<DZImageTileDescriptor> ImageList()
        {
            int ncol = (int)Math.Ceiling(Size.Width / ((float)_tileSize));
            int nrow = (int)Math.Ceiling(Size.Height / ((float)_tileSize));

            return from icol in Enumerable.Range(0, ncol)
                   from irow in Enumerable.Range(0, nrow)
                   select new DZImageTileDescriptor()
                    {
                        X = _tileSize * ((ulong)icol),
                        Y = _tileSize * ((ulong)irow),
                        Width = ((uint)(icol != (ncol - 1) ? _tileSize : (ulong)Size.Width - _tileSize * ((ulong)ncol - 1))) + OverlapPadding(icol, ncol),
                        Height = ((uint)(irow != (nrow - 1) ? _tileSize : (ulong)Size.Height - _tileSize * ((ulong)nrow - 1))) + OverlapPadding(irow, nrow),
                        Name = string.Format("{0}_{1}.png", icol.ToString(), irow.ToString())
                    };
        }

        /// <summary>
        /// Depending on where we are in the sequence, compute the overlap.
        /// </summary>
        /// <param name="icol"></param>
        /// <param name="ncol"></param>
        /// <returns></returns>
        private uint OverlapPadding(int index, int limit)
        {
            uint result = 0;
            if (index > 0)
                result++;
            if (index < (limit - 1))
                result++;

            return result;
        }
    }
}
